/*
 * Library.java
 * 
 * Made by Olof Ekelund, Ludvig Gee, Yacoub Sattar 
 * October 19 2012.
 * 
 * This class takes a file (Books.txt) and sorts out the
 * lines which contain complete information about a 
 * book and is correctly formatted and writes them in a
 * new file (NewBooks.txt), lines which contain errors 
 * are written in another file (ErrorLines.txt).
 * 
 * Version 1.0
 *  
 * Copyright Olof Ekelund, Ludvig Gee, Yacoub Sattar.
 */


import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import javax.swing.JFileChooser;

public class Library {
	static ErrorLines errorLines;
	static NewBooks newBooks;
	
	
	public static void main(String[] args){
		try{
			errorLines = new ErrorLines();
			newBooks = new NewBooks();
			
			String pathway = null;	
			
			//Jfilechooser choose books.txt file			 
			JFileChooser fileChooser = new JFileChooser();
			fileChooser.setDialogTitle("Choose Books.txt");
			if (fileChooser.showOpenDialog(null)== JFileChooser.APPROVE_OPTION){					 
				java.io.File file = fileChooser.getSelectedFile();					 
				Scanner input = new Scanner(file);				 
									 
				while(input.hasNextLine()){
					processLine(input.nextLine());
				}
				input.close();
			}
			else {
				System.out.println("No file selected");
			}
			
			//Open new dialogbox to choose directory.	
			fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			fileChooser.setDialogTitle("Choose your save folder");
			fileChooser.setApproveButtonText("Save");
			if (fileChooser.showOpenDialog(null)== JFileChooser.APPROVE_OPTION){
				pathway = ((fileChooser.getSelectedFile()).getAbsolutePath());
			}
			
			newBooks.setFilepath(pathway);
			errorLines.setFilepath(pathway);
		
			newBooks.writeListToFile();
			errorLines.writeListToFile();
			
			System.out.println(newBooks.getListSize() + " lines were added to NewBooks.txt.");
			System.out.println(errorLines.getListSize() + " lines were added to ErrorLines.txt.");
			
		}catch(FileNotFoundException e){
			System.out.println("File Not Found.");
		}catch(Exception e){
			System.out.println(e);
		}
	}
	
	private static void processLine(String line){
		Books book = new Books();
		String token = "";
		String errors = "Errors in entry: ";
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd");
		Scanner scan = new Scanner(line);
		scan.useDelimiter("#");
		boolean lineContainsErrors = false;
		
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token) && checkISBN(token))
				book.setISBN(token);
			else{
				errors += "ISBN ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token) && stringIsNumeric(token))
				book.setCopyNumber(Integer.parseInt(token));
			else{
				errors += "CopyNumber ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token))
				book.setTitle(token);
			else{
				errors += "Title ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token))
				book.setAuthor(token);
			else{
				errors += "Author ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token))
				book.setPublisher(token);
			else{
				errors += "Publisher ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token) && stringIsNumeric(token))
				book.setYear(Integer.parseInt(token));
			else{
				errors += "Year ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token) && stringIsNumeric(token))
				book.setStatistics(Integer.parseInt(token));
			else{
				errors += "Statistics ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token) && isValidDate(token)){
				try{
					book.setBorrowDate(dateFormat.parse(token.trim()));
				}catch(ParseException e){
					System.out.println(e);
				}
			}
			else{
				errors += "BorrowDate ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token) && isValidDate(token)){
				try{
					book.setReturnDate(dateFormat.parse(token.trim()));
				}catch(ParseException e){
					System.out.println(e);
				}
			}
			else{
				errors += "ReturnDate ";
				lineContainsErrors = true;
			}
		}
		if(scan.hasNext()){
			token = scan.next();
			if(stringIsNotEmpty(token) && stringIsNumeric(token))
				book.setLibraryCardNumber(Integer.parseInt(token));
			else{
				errors += "LibraryCard ";
				lineContainsErrors = true;
			}
		}
		if((book.getReturnDate().compareTo(book.getBorrowDate())<0) && !(book.getReturnDate().equals(new Date(0)))){
				errors += "Return > Borrow";
				lineContainsErrors = true;
		}
		if(lineContainsErrors){
			errorLines.addLine(errors + "//" + line + "\n");
		}
		else
			newBooks.addBook(book);
		
		scan.close();
	}
	
	private static boolean stringIsNumeric(String s){
		try{
			Long.parseLong(s);
		}catch(NumberFormatException e){
			return false;
		}
		return true;
	}
	
	private static boolean stringIsNotEmpty(String s){
		return(!s.equals(""));
	}
	
	private static boolean isValidDate(String s){
		if (s.equals(""))
			return false;
		
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd");
	    
	    if (s.length() != dateFormat.toPattern().length())
	    	return false;
	    
	    dateFormat.setLenient(false);
	    
	    try {
	    	dateFormat.parse(s.trim());
	    }catch (ParseException e) {
	    	return false;
	    }
	    return true;
	}
	
	private static boolean checkISBN(String ISBNString){
		Long moduloNumber = 10L;
		Long ISBN = 0L;
		int finalDigit = 0;
		int sum = 0;
		int multiplier = 0;
		int result = 0;
		
		if(ISBNString.length() == 13 && stringIsNumeric(ISBNString)){
			ISBN = Long.valueOf(ISBNString.substring(0, 12));
			finalDigit = Integer.valueOf(ISBNString.substring(12));
			
			for(int i = 0; i < 12; i++){
				if(i % 2 == 0)
					multiplier = 3;
				else if(i % 2 == 1)
					multiplier = 1;
					sum += (int)(((ISBN % moduloNumber) / (moduloNumber / 10)) * multiplier);
					moduloNumber *= 10;
			}
		
			result = 10 - (sum % 10);
		
			if(result == finalDigit)
				return true;
			
			else
				return false;
		}
		
		else
			return false;
	}
}
